/***********************************************************************************
Copy right:	    hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"
#include "thttpd.h"
#define KB 1024

//普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
                  "Connection: close\r\n"

struct msgbuf mq;                               //消息队列对象
static struct std_node *handle_share(int sock); //共享内存函数
int handle_msgqueue(void);                      //消息内存函数
static int handle_login(int sock, const char *input)
{
    char reply_buf[HTML_SIZE] = {0};
    char *uname = strstr(input, "username="); //从返回字符串的第一次的指针
    uname += strlen("username=");             //指针移动到username=后面
    char *p = strstr(input, "password");
    *(p - 1) = '\0'; //username=admin&password=admin 把&变成了\0 作为字符串结束的标志
    printf("username = %s\n", uname);

    char *passwd = p + strlen("password="); //指针移动到password=后面
    printf("passwd = %s\n", passwd);

    if (strcmp(uname, "admin") == 0 && strcmp(passwd, "admin") == 0) //比较账户名和密码是否正确
    {
        sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname); //存到本地仓库里
        strcat(reply_buf, "<script>window.location.href = '/index.html';</script>");                //跳转到index.html
        send(sock, reply_buf, strlen(reply_buf), 0);
    }
    else
    {
        printf("web login failed\n");

        //"用户名或密码错误"提示，chrome浏览器直接输送utf-8字符流乱码，没有找到太好解决方案，先过渡
        char out[128] = {0xd3, 0xc3, 0xbb, 0xa7, 0xc3, 0xfb, 0xbb, 0xf2, 0xc3, 0xdc, 0xc2, 0xeb, 0xb4, 0xed, 0xce, 0xf3};
        sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);   //提示对话框
        strcat(reply_buf, "<script>window.location.href = '/login.html';</script>"); //自己跳转到自己
        send(sock, reply_buf, strlen(reply_buf), 0);
    }

    return 0;
}
static int handle_add(int sock, const char *input)
{
    // mq.type = 10;
    // int number1, number2;
    long type;
    int key, value;
    printf("input:%s\n", input); //显示
    //input必须是"data1=1data2=6"类似的格式，注意前端过来的字符串会有双引号
    sscanf(input, "\"type=%ldkey=%dvalue=%d\"", &(mq.type), &(mq.key), &(mq.val.b_val)); //将前端的值赋值到后端
    int msgid = handle_msgqueue();
    msgsnd(msgid, &mq, sizeof(mq) - sizeof(long), 0); // 0：代表发完返回否则阻塞  //发送给消息队列

    printf("mq.type:%ld  mq.key:%d  mq.value:%d \n", mq.type, mq.key, mq.val.b_val);

    type = mq.type;
    key = mq.key;
    value = mq.val.b_val;

    char reply_buf[HTML_SIZE] = {0};
    if (type == 10 && key == 104 && value == 1)
    {
        strcpy(reply_buf, "通风扇打开");
    }
    else if (type == 10 && key == 104 && value == 0)
    {
        strcpy(reply_buf, "通风扇关闭");
    }
    else if (type == 10 && key == 105 && value == 1)
    {
        strcpy(reply_buf, "灯打开");
    }
    else if (type == 10 && key == 105 && value == 0)
    {
        strcpy(reply_buf, "灯关闭");
    }
    if (type == 10 && key == 106 && value == 1)
    {
        strcpy(reply_buf, "阀门打开");
    }
    else if (type == 10 && key == 106 && value == 0)
    {
        strcpy(reply_buf, "阀门关闭");
    }
    else if (type == 10 && key == 107 && value == 1)
    {
        strcpy(reply_buf, "报警器打开");
    }
    else if (type == 10 && key == 107 && value == 0)
    {
        strcpy(reply_buf, "报警器关闭");
    }
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);
    return 0;
}
static struct std_node *handle_share(int sock)
{
    struct shm_param param;
    int shmid;
    int *num = NULL;
    struct std_node *p = NULL;
    //创建或者打开共享内存
    shmid = shm_init(&param, "shm.txt", sizeof(param));
    char reply_buf[HTML_SIZE] = {0};
    if (shmid < 0)
    {
        perror("shm init err\n");
        return NULL;
    }
    printf("共享内存 :shmid: %d\n", shmid);
    //映射共享内存
    num = shm_getaddr(&param);
    p = (struct std_node *)(num + 1);
    p = (struct std_node *)(p + 5); //偏移量  stm32的是前5个
    if (p == NULL)
    {
        perror("shmat get arr err\n");
        return NULL;
    }
    return p;
}

// 消息队列
// int handle_msgqueue(void)
// {
//     int msgid;
//     struct msgbuf msg;
//     msgid=msg_queue_send("msg",&msg,sizeof(msg),0);
//     if (msgid <=0)
//     {
//         perror("Failed to send message");
//     }
//     printf("消息队列 msgid: %d\n", msgid);
//     return msgid;
// }

//消息队列
int handle_msgqueue(void)
{
    key_t key;
    int msgid;
    if ((key = ftok("/mnt/msg.txt",'b')) < 0)
    {
        perror("que wangye  ftok err");
        return -1;
    }
    printf("key = %#x\n", key);

    //打开或创建消息队列
    msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0666); //创建消息队列，如果之前有就返回-1
    if (msgid <= 0)
    {
        if (errno == EEXIST)
            msgid = msgget(key, 0666); //直接打开消息队列
        else
        {
            perror("msgget err");
            return -1;
        }
    }
    printf("msgid handle_msgqueue: %d\n", msgid);
    return msgid;
}
/**
 * @brief 处理自定义请求，在这里添加进程通信
 * @param input
 * @return
 */
int parse_and_process(int sock, const char *query_string, const char *input)
{
    //query_string不一定能用的到
    printf("input:%s\n", input); //浏览器也发过来了list
    //先处理登录操作
    if (strstr(input, "username=") && strstr(input, "password="))
    {
        return handle_login(sock, input);
    }
    //处理求和请求
    else if (strstr(input, "type=") && strstr(input, "key=") && strstr(input, "value="))
    {
        printf("-------%s----%s----%d----\n", __FILE__, __func__, __LINE__);
        return handle_add(sock, input);
    }
    else if (strcmp(input, "list") == 0) //输入list读出设备信息
    {
        printf("-------%s----%s----%d----\n", __FILE__, __func__, __LINE__);
        struct std_node *p = handle_share(sock);
        struct std_node *end = p + (3 * sizeof(struct std_node)); // 计算共享内存3个内存空间
        int num_registers_to_read = 3;                            //共3个寄存器
        int i = 0;
        char buf[32] = {0};
        char buffer[32] = {0};
        while (i < num_registers_to_read && p < end)
        {
            //把内容取出共享内存                                    //后期需要修改
            // 假设我们只关心 i_val，所以将读取的值转换为 int 并存储
            if (i == 0)
            {
                sprintf(buffer, "%d ", p->new_val.i_val);
                strcat(buf, buffer);
            }
            else
            {
                sprintf(buffer, "%.2f ", p->new_val.f_val);
                strcat(buf, buffer);
            }
            // 输出变化（如果需要）
            // 移动到下一个 std_node
            p++;
            i++;
        }
        // 发送HTTP响应给客户端
        printf("buf:%s\n", buf);
        printf("-------%s----%s----%d----\n", __FILE__, __func__, __LINE__);

        send(sock, buf, strlen(buf), 0);
    }
    else //剩下的都是json请求，这个和协议有关了
    {
        // 构建要回复的JSON数据   //*******JSON********
        const char *json_response = "{\"message\": \"Hello, client!\"}";
        // 发送HTTP响应给客户端
        send(sock, json_response, strlen(json_response), 0);
    }
    return 0;
}
